﻿#pragma once
#include "yzrutil.h"
#include "array/Array.hpp"
#include "FilterPassType.h"

namespace yzrilyzr_dsp{
	class IIR;
	class BiquadIIR;
	EBCLASS(IIRUtil){
		public:
		static std::shared_ptr<IIR> newButterworthIIRFilter(u_sample_rate sampleRate, FilterPassType type, uint16_t n, u_freq f1, u_freq f2);
		/**
		 * @param n  阶数
		 * @param f1 数字角频率，起始
		 * @param f2 数字角频率，结束（高通低通填0即可）
		 */
		static std::shared_ptr<IIR> newButterworthIIRFilter(FilterPassType type, uint16_t n, u_freq f1, u_freq f2);
		static std::shared_ptr<IIR> newC1C3IIRFilter(u_freq freq, double c1, double c3);
		static void C1C3IIRFilter(IIR & iir, u_freq freq, double c1, double c3);
		static std::shared_ptr<BiquadIIR> newBiquadIIRFilter(u_freq f0, u_sample_rate sampleRate, double Q, FilterPassType type);
		static std::shared_ptr<BiquadIIR> newBiquadIIRFilter(u_freq f0, u_sample_rate sampleRate, double Q, double gain, FilterPassType type);
		static std::shared_ptr<yzrilyzr_array::DoubleArray> * design(FilterPassType filterPassType, uint16_t filterOrder, u_freq fcf1, u_freq fcf2);
		//--- A coefficients -----------------------------------------------------------
		static std::shared_ptr<yzrilyzr_array::DoubleArray>
			calculateACoefficients(FilterPassType filterPassType, uint16_t filterOrder, u_freq fcf1, u_freq fcf2);
			//--- B coefficients -----------------------------------------------------------
			// Calculates the B coefficients.
		static std::shared_ptr<yzrilyzr_array::DoubleArray>
			calculateBCoefficients(FilterPassType filterPassType, uint16_t filterOrder, u_freq fcf1, u_freq fcf2);
			//--- Scaling factor -----------------------------------------------------------
			// Calculates the scaling factor.
			// The scaling factor is what the B coefficients must be multiplied by so
			// that the filter response has a maximum value of 1.
		static double calculateScalingFactor(FilterPassType filterPassType, uint16_t filterOrder, u_freq fcf1, u_freq fcf2);
		// Calculates the A coefficients for a lowpass or highpass filter.
		static std::shared_ptr<yzrilyzr_array::DoubleArray> calculateACoefficients_lp_hp(uint16_t n, u_freq fcf);
		// Calculates the A coefficients for a bandpass or bandstop filter.
		static std::shared_ptr<yzrilyzr_array::DoubleArray> calculateACoefficients_bp_bs(FilterPassType filterPassType, uint16_t n, u_freq f1f, u_freq f2f);
		// Calculates the B coefficients for a lowpass filter.
		static std::shared_ptr<yzrilyzr_array::IntArray> calculateBCoefficients_lp(uint16_t n);
		// Calculates the B coefficients for a highpass filter.
		static std::shared_ptr<yzrilyzr_array::IntArray> calculateBCoefficients_hp(uint16_t n);
		// Calculates the B coefficients for a bandpass filter.
		static std::shared_ptr<yzrilyzr_array::IntArray> calculateBCoefficients_bp(uint16_t n);
		// Calculates the B coefficients for a bandstop filter.
		static std::shared_ptr<yzrilyzr_array::DoubleArray> calculateBCoefficients_bs(uint16_t n, u_freq f1f, u_freq f2f);
		// Calculates the scaling factor for a lowpass or highpass filter.
		static double calculateScalingFactor_lp_hp(FilterPassType filterPassType, uint16_t n, u_freq fcf);
		// Calculates the scaling factor for a bandpass or bandstop filter.
		static double calculateScalingFactor_bp_bs(FilterPassType filterPassType, uint16_t n, u_freq f1f, u_freq f2f);
		//------------------------------------------------------------------------------
		static std::shared_ptr<yzrilyzr_array::DoubleArray> binomial_mult(uint16_t n, yzrilyzr_array::DoubleArray & p);
		// Multiplies a series of trinomials together and returns the coefficients
		static std::shared_ptr<yzrilyzr_array::DoubleArray> trinomial_mult(uint16_t n, yzrilyzr_array::DoubleArray & b, yzrilyzr_array::DoubleArray & c);
		static double groupDelay(IIR & iir, u_freq freq, u_sample_rate sampleRate);
		static double groupDelay(BiquadIIR & iir, u_freq freq, u_sample_rate sampleRate);
		static double groupDelay(yzrilyzr_array::DoubleArray & aCoeff, yzrilyzr_array::DoubleArray & bCoeff, u_freq freq, u_sample_rate sampleRate);
		static std::shared_ptr<yzrilyzr_array::DoubleArray> cascade(yzrilyzr_array::DoubleArray & poly1, yzrilyzr_array::DoubleArray & poly2);
		static void biquad(BiquadIIR & iir, u_freq f0, u_sample_rate sampleRate, double Q, FilterPassType type, double gain=0);
		static void biquad(yzrilyzr_array::DoubleArray & aCoeff, yzrilyzr_array::DoubleArray & bCoeff, u_freq f0, u_sample_rate sampleRate, double Q, FilterPassType type, double gain=0);
		static double calculateThiranDelay(double bandwidth, double frequency, int32_t filterOrder);
		static void designThiranFilter(BiquadIIR & filter, double targetDelay);
		static void designThiranFilter(yzrilyzr_array::DoubleArray & aCoeff, yzrilyzr_array::DoubleArray & bCoeff, double targetDelay, int filterStages);
		static u_freq limitFreq(u_sample_rate sampleRate, u_freq f);
	};
}